/*
 * LightControl.c
 *
 *  Created on: 21.09.2011
 *      Author: windows97
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include "Globals.h"
#include "HwAbstraction.h"
#include "TimerControl.h"
#include "LightControl.h"

#define PERCENT_MIN_U8          ((uint8_t) (0U))
#define PERCENT_MAX_U8          ((uint8_t) (100U))

#define HEARTBEAT_2_U16         ((uint16_t) ((F_CPU/HEARTBEAT_PRESCALER)*0.01 /*s*/)) /* -> 10ms: XTAL/HEARTBEAT_PRESCALER * 0,010s */
//#define BRIGHTNESS_MIN_U16      ((uint16_t) ((F_CPU/HEARTBEAT_PRESCALER)*0.0021 /*s*/)) /*((uint16_t)(225U)) 450U @ 10MHz calculation TBD */
#define BRIGHTNESS_MIN_U16      ((uint16_t) ((F_CPU/HEARTBEAT_PRESCALER)*0.000340 /*s*/)) /*((uint16_t)(225U)) 450U @ 10MHz calculation TBD */
#define BRIGHTNESS_MAX_U16      ((uint16_t) ((F_CPU/HEARTBEAT_PRESCALER)*0.010 /*s*/)) /* -> 10ms: XTAL/HEARTBEAT_PRESCALER * 0,010s */
#define BRIGHTNESS_STEP_U8      ((uint16_t)(1U))
#define TRIAC_TRIGGER_TIME_U16  ((uint16_t) ((F_CPU/HEARTBEAT_PRESCALER)*0.001 /*s*/)) /* triac trigger time: 1ms */
#define TRIAC_TRIGGER_COUNT_U8  ((uint8_t) (5U))
volatile uint8_t  gLcoTriggerTriac_u8   = 0;
static uint16_t   gLcoReloadValue_u16 = BRIGHTNESS_MAX_U16;
static T_Light    gLightOn              = LightOff;
static uint8_t    gLcoBrightnessPercent_u8  = 0;
static uint8_t    gLcoBrightnessMaxPercent_u8 = 100;

static inline void LcoReCalcReloadValue( void );

/* purpose:
 * phase angle control
 */
ISR(LIGHT_OC_INT)
{
  if (0 != gLcoTriggerTriac_u8)
  {
    SET_TRIAC_OUT_PIN;
    OCR1B += TRIAC_TRIGGER_TIME_U16;
    gLcoTriggerTriac_u8 = 0;
  }
  else
  {
    CLR_TRIAC_OUT_PIN;
  }
}

/*
 * purpose:
 * detection of zero crossing
 */
ISR(LIGHT_INT)
{
  /* TODO (11-10-05): switch to Brightness percent */
  OCR1B = TCNT1 + gLcoReloadValue_u16;
  gLcoTriggerTriac_u8 = TRIAC_TRIGGER_COUNT_U8;
  CLR_TRIAC_OUT_PIN;
}

void LcoInit( void )
{
  gLcoBrightnessPercent_u8 = 0;
  INT_CONTROL = ((INT_CONTROL & ~(INT0_INT_CLEARFLAGS)) | INT0_RISING_EDGE );
  OCR1B       = HEARTBEAT_2_U16;
}

uint8_t LcoGetBrightness( void )
{
  return (gLcoBrightnessPercent_u8);
}

void LcoSetBrightness( uint8_t iPercent_u8 )
{
  /* calculate new brightness based on given value and maximum brightness */
  gLcoBrightnessPercent_u8 = (gLcoBrightnessMaxPercent_u8/100)*iPercent_u8;
  LcoReCalcReloadValue();
}

void LcoIncBrightness( void )
{
  /* TODO (11-10-05): switch to Brightness percent */
  if( gLcoBrightnessPercent_u8 < (PERCENT_MAX_U8 - BRIGHTNESS_STEP_U8 ))
  {
    gLcoBrightnessPercent_u8 += BRIGHTNESS_STEP_U8;
    LcoReCalcReloadValue();
  }
}

void LcoDecBrightness( void )
{
  /* TODO (11-10-05): switch to Brightness percent */
  if( gLcoBrightnessPercent_u8 >= BRIGHTNESS_STEP_U8 )
  {
    gLcoBrightnessPercent_u8 -= BRIGHTNESS_STEP_U8;
    LcoReCalcReloadValue();
  }
}

void LcoSetLight( T_Light iOnOff )
{
  if( ( LightOff != iOnOff) &&
      ( 0 < gLcoBrightnessPercent_u8 )) /* to assure that the light is not set to on, if the light level is 0 */
  {
    gLightOn = LightOn;
    /* switch on */
    SET_LIGHT_INT;
    SET_LIGHT_OC_INT;
  }
  else
  { /* switch off */
    gLightOn = LightOff;
    CLR_LIGHT_INT;
    CLR_LIGHT_OC_INT;
  }
}

T_Light LcoGetLight( void )
{
  return (gLightOn);
}

void LcoToggleLight( void )
{
  /*determine light status */
  if( LightOff != gLightOn )
  { /* switch light off */
    LcoSetLight( LightOff );
  }
  else
  { /* switch light on */
    LcoSetLight( LightOn );
  }
}


void LcoSetBrightnessMax( uint8_t iPercent_u8 )
{
  if( ( PERCENT_MIN_U8 >= iPercent_u8 ) &&
      ( PERCENT_MAX_U8 <= iPercent_u8 ) )
  {
    gLcoBrightnessMaxPercent_u8 = iPercent_u8;
  }
}

static inline void LcoReCalcReloadValue( void )
{
  gLcoReloadValue_u16 = BRIGHTNESS_MAX_U16 - (((BRIGHTNESS_MAX_U16 - BRIGHTNESS_MIN_U16)/100)*gLcoBrightnessPercent_u8);
  UART_PUT_VALUE( "gLcoReloadValue_u16: ", gLcoReloadValue_u16 );
}
